package org.jsola.hr.service.impl.syncSoc;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.jsola.cache.ICache;
import org.jsola.exception.ParamException;
import org.jsola.hr.common.BeanCopyUtil;
import org.jsola.hr.common.CacheKeyKit;
import org.jsola.hr.common.DateUtils;
import org.jsola.hr.common.QdSocWebSite;
import org.jsola.hr.common.sm4.SM4Utils;
import org.jsola.hr.constant.HrConstants;
import org.jsola.hr.constant.QdWebSiteDeclReason;
import org.jsola.hr.constant.QdWebSiteSocTypeIndex;
import org.jsola.hr.constant.SocPayCostType;
import org.jsola.hr.dao.IEmpSocItemDAO;
import org.jsola.hr.dto.EmpSocPlanAttachDTO;
import org.jsola.hr.dto.SocAccountDTO;
import org.jsola.hr.dto.SyncSocUniversalDTO;
import org.jsola.hr.dto.SyncSocWebSiteDTO;
import org.jsola.hr.dto.syncSocDTO.*;
import org.jsola.hr.entity.*;
import org.jsola.hr.exception.HrException;
import org.jsola.hr.query.SocCheckCustomQuery;
import org.jsola.hr.service.*;
import org.jsola.user.core.TokenUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import static org.jsola.hr.constant.EmpSocStatus.NORMAL_SOC;
import static org.jsola.hr.constant.HrConstants.*;
import static org.jsola.hr.constant.SocPayCostType.*;

/**
 * @author lyh
 */
@Slf4j
@Service("hrQingDaoSyncSocServiceImpl")
public class QingDaoSyncSocServiceImpl implements ISyncSocInterface {

    @Autowired
    private ICache cache;

    @Autowired
    private IEmpSocMonthService empSocMonthService;

    @Autowired
    private IEmpInfoService empInfoService;

    @Autowired
    private IEmpSocInfoService empSocInfoService;

    @Autowired
    private IEmpSocItemDAO empSocItemDAO;

    @Autowired
    private IEmpSocItemService empSocItemService;

    @Autowired
    private IEmpSocRelatedService empSocRelatedService;

    @Autowired
    private IEmpSocPlanService empSocPlanService;

    @Autowired
    private IZtcConfigService ztcConfigService;

    @Override
    public <T> List<T>  incrementSocEmp(SyncSocWebSiteDTO syncSocWebSiteDTO, TokenUser tokenUser) {
        // 获取这个账号的accessToken
        ZtcConfigDO ztcConfigDO = ztcConfigService.selectByCompanyId(syncSocWebSiteDTO.getCompanyId());
        String accessTokenKey = CacheKeyKit.getAccessTokenByAppId(ztcConfigDO.getAppId());
        String accessToken = cache.get(accessTokenKey);
        List<T> result = new ArrayList<>();
        SocAccountDTO socAccountDTO = cache
                .get(CacheKeyKit.getSocAccount(tokenUser.getUserId(), syncSocWebSiteDTO.getAreaId()));
        List<QdIncrementCheckDTO> extraInfo = syncSocWebSiteDTO.getExtraInfo();
        List<String> empIdList = extraInfo.stream()
                .map(QdIncrementCheckDTO::getEmpId)
                .collect(Collectors.toList());
        List<EmpInfoDO> empInfoList = empInfoService.selectDoByIds(empIdList);
        Map<String, EmpInfoDO> empMap = empInfoList.stream().collect(Collectors.toMap(EmpInfoDO::getId, v -> v));
        for (QdIncrementCheckDTO checkDTO : extraInfo) {
            EmpInfoDO empInfoDO = empMap.get(checkDTO.getEmpId());
            if (ObjectUtils.isEmpty(empInfoDO)) {
                throw new ParamException("身份证号为\"" + empInfoDO.getIdCard() + "\"的员工不存在");
            }
            String increment = QdSocWebSite.increment(empInfoDO, ztcConfigDO.getAppId(),
                    checkDTO, accessToken, socAccountDTO.getCookie());
            String responseJson = SM4Utils.getDecStr(increment, ztcConfigDO.getOfficialKey());
            QdResponseDTO incrementResponse = JSONObject.parseObject(responseJson, QdResponseDTO.class);
            incrementResponse.setSyncType(INCREASE_STR);
            incrementResponse.setName(checkDTO.getXm());
            result.add((T) incrementResponse);
            EmpSocPlanAttachDTO empSocPlanAttachDTO = new EmpSocPlanAttachDTO();
            empSocPlanAttachDTO.setCompanyId(syncSocWebSiteDTO.getCompanyId());
            empSocPlanAttachDTO.setSocPlanIdList(Collections.singletonList(checkDTO.getPlanId()));
            if("0".equals(incrementResponse.getRespCode())){
                empSocPlanAttachDTO.setExecuteResult(2);
                empSocPlanAttachDTO.setFailCause(incrementResponse.getRespMsg());
            } else {
                empSocPlanAttachDTO.setExecuteResult(1);
            }
            //empSocPlanService.increaseFeedback(empSocPlanAttachDTO, tokenUser);
        }
        return result;
    }

    @Override
    public <T> List<T> decreaseSocEmp(SyncSocWebSiteDTO syncSocWebSiteDTO, TokenUser tokenUser) {
        // 获取这个账号的accessToken
        ZtcConfigDO ztcConfigDO = ztcConfigService.selectByCompanyId(syncSocWebSiteDTO.getCompanyId());
        String accessTokenKey = CacheKeyKit.getAccessTokenByAppId(ztcConfigDO.getAppId());
        String accessToken = cache.get(accessTokenKey);
        List<T> result = new ArrayList<>();
        List<QdAttritionCheckDTO> extraInfo = syncSocWebSiteDTO.getAttritionExtraInfo();
        List<String> empIdList = extraInfo.stream()
                .map(QdAttritionCheckDTO::getEmpId)
                .collect(Collectors.toList());
        List<EmpInfoDO> empInfoList = empInfoService.selectDoByIds(empIdList);
        Map<String, EmpInfoDO> empMap = empInfoList.stream().collect(Collectors.toMap(EmpInfoDO::getId, v -> v));
        for (QdAttritionCheckDTO checkDTO : extraInfo) {
            QdWebSiteAttritionExtraInfo empExtraInfo = checkDTO.getExtraInfo();
            EmpInfoDO empInfoDO = empMap.get(checkDTO.getEmpId());
            String attrition = QdSocWebSite.attrition(accessToken, ztcConfigDO.getAppId(), empInfoDO, empExtraInfo);
            String responseJson = SM4Utils.getDecStr(attrition, ztcConfigDO.getOfficialKey());
            QdResponseDTO response = JSONObject.parseObject(responseJson, QdResponseDTO.class);
            response.setSyncType(DECREASE_STR);
            response.setName(checkDTO.getXm());
            result.add((T) response);
            EmpSocPlanAttachDTO empSocPlanAttachDTO = new EmpSocPlanAttachDTO();
            empSocPlanAttachDTO.setCompanyId(syncSocWebSiteDTO.getCompanyId());
            empSocPlanAttachDTO.setSocPlanIdList(Collections.singletonList(checkDTO.getPlanId()));
            if("0".equals(response.getRespCode())){
                empSocPlanAttachDTO.setExecuteResult(2);
                empSocPlanAttachDTO.setFailCause(response.getRespMsg());
            } else {
                empSocPlanAttachDTO.setExecuteResult(1);
            }
            //empSocPlanService.decreaseFeedback(empSocPlanAttachDTO, tokenUser);
        }
        return result;
    }

    @Override
    public int incrementMeEmp(SyncSocWebSiteDTO syncSocWebSiteDTO, TokenUser tokenUser) {
        return 0;
    }

    @Override
    public int decreaseMeEmp(SyncSocWebSiteDTO syncSocWebSiteDTO, TokenUser tokenUser) {
        return 0;
    }

    @Override
    public int incrementPfEmp(SyncSocWebSiteDTO syncSocWebSiteDTO, TokenUser tokenUser) {
        return 0;
    }

    @Override
    public int decreasePfEmp(SyncSocWebSiteDTO syncSocWebSiteDTO, TokenUser tokenUser) {
        return 0;
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public List<SyncSocUniversalDTO> batchSyncSocInfo(SyncSocWebSiteDTO syncSocWebSiteDTO, TokenUser tokenUser) {
        List<SyncSocUniversalDTO> resultList = new ArrayList<>();
        String companyId = syncSocWebSiteDTO.getCompanyId();
        SocAccountDTO socAccountDTO = cache.get(CacheKeyKit.getSocAccount(tokenUser.getUserId(), syncSocWebSiteDTO.getAreaId()));
        if (ObjectUtils.isEmpty(socAccountDTO)) {
            throw new ParamException("请重新登录社保账号/或刷新社保账号页面");
        }
        // 拿到比例
        List<QingDaoCardinalityDefaultDTO> cardinalityDefaultList;
        try {
            String cardinalityDefaultStr = QdSocWebSite.getCardinalityDefault(socAccountDTO.getCookie());
            log.info("获取青岛社保子项比例:{}", cardinalityDefaultStr);
            cardinalityDefaultList =
                    JSONObject.parseArray(JSON.parseObject(cardinalityDefaultStr).getString("data"), QingDaoCardinalityDefaultDTO.class);
        } catch (Exception e) {
            throw new ParamException("请刷新页面后重试");
        }
        cardinalityDefaultList.forEach(qingDaoCardinalityDefaultDTO -> {
            if ("企业养老".equals(qingDaoCardinalityDefaultDTO.getXz())) {
                qingDaoCardinalityDefaultDTO.setXz("养老保险");
            } else {
                qingDaoCardinalityDefaultDTO.setXz(qingDaoCardinalityDefaultDTO.getXz() + "保险");
            }
            qingDaoCardinalityDefaultDTO.setGrjfbl(qingDaoCardinalityDefaultDTO.getGrjfbl().substring(0, qingDaoCardinalityDefaultDTO.getGrjfbl().length() - 1).trim());
            qingDaoCardinalityDefaultDTO.setDwjfbl(qingDaoCardinalityDefaultDTO.getDwjfbl().substring(0, qingDaoCardinalityDefaultDTO.getDwjfbl().length() - 1).trim());
        });
        // 按照险种分组
        Map<String, QingDaoCardinalityDefaultDTO> cardinalityDefaultGroupType =
                cardinalityDefaultList.stream().collect(Collectors.toMap(QingDaoCardinalityDefaultDTO::getXz, v -> v));
        // 得先调一次获取total,根据total拿到页数
        String payDetailInfoBody = QdSocWebSite.getPayDetailInfo(syncSocWebSiteDTO.getStartDate(),
                syncSocWebSiteDTO.getEndDate(), socAccountDTO.getCookie(), 0);
        JSONObject responseDate = JSON.parseObject(payDetailInfoBody);
        if (ObjectUtils.isEmpty(responseDate)) {
            return new ArrayList<>();
        }
        Integer total = responseDate.getInteger("total");
        int maxPage = (total + 100 - 1) / 100;
        // 拿到第0页的数据
        String zeroPageDate = JSON.parseObject(payDetailInfoBody).getString("data");
        List<QdWebSitePayDetailDTO> zeroPageDateList = JSONObject.parseArray(zeroPageDate, QdWebSitePayDetailDTO.class);
        if (CollectionUtils.isEmpty(zeroPageDateList)) {
            return new ArrayList<>();
        }
        List<QdWebSitePayDetailDTO> totalQdWebSitePayDetailDTO = new ArrayList<>(zeroPageDateList);
        //循环剩下的几页数据
        for (int i = 1; i < maxPage; i++) {
            String payDetailInfo = QdSocWebSite.getPayDetailInfo(syncSocWebSiteDTO.getStartDate(),
                    syncSocWebSiteDTO.getEndDate(), socAccountDTO.getCookie(), i);
            String data = JSON.parseObject(payDetailInfo).getString("data");
            List<QdWebSitePayDetailDTO> qdWebSitePayDetailList = JSONObject.parseArray(data, QdWebSitePayDetailDTO.class);
            totalQdWebSitePayDetailDTO.addAll(qdWebSitePayDetailList);
        }
        // 对象 copy 为通用对象
        List<SyncSocUniversalDTO> syncSocUniversalList =
                BeanCopyUtil.beanListCopy(totalQdWebSitePayDetailDTO, SyncSocUniversalDTO.class);
        parseSyncSocUniversalDTOList(syncSocUniversalList);
        // 按照缴费年月分组
        Map<String, List<SyncSocUniversalDTO>> payDetailGroupDate =
                syncSocUniversalList.stream().collect(Collectors.groupingBy(SyncSocUniversalDTO::getPaymentDate));
        for (String dateStr : payDetailGroupDate.keySet()) {
            String[] yearAndMonth = DateUtils.getYearAndMonthByDateString(dateStr);
            String monthId;
            monthId = empSocMonthService.selectMonthIdByYearAndMonth(companyId, yearAndMonth[0],
                    yearAndMonth[1], tokenUser.getSiteId());
            if (StringUtils.isEmpty(monthId)) {
                monthId = empSocMonthService
                        .saveByYearAndMonth(companyId, yearAndMonth[0], yearAndMonth[1], tokenUser)
                        .getId();
            }
            List<SyncSocUniversalDTO> payDetailOneMonthList = payDetailGroupDate.get(dateStr);
            // 在根据缴费所属年月的基础上按照员工姓名分组
            Map<String, List<SyncSocUniversalDTO>> payDetailGroupName =
                    payDetailOneMonthList.stream().collect(Collectors.groupingBy(SyncSocUniversalDTO::getEmpName));
            for (String empNameKey : payDetailGroupName.keySet()) {
                List<SyncSocUniversalDTO> payDetailOneEmp = payDetailGroupName.get(empNameKey);
                String empName = payDetailOneEmp.get(0).getEmpName();
                String idCard = payDetailOneEmp.get(0).getIdCard();
                String payCostType = payDetailOneEmp.get(0).getPayCostType();
                // 查询花名册有无此人
                EmpInfoDO empInfoDO = empInfoService.selectEmpByNameAndIdCard(empName, idCard, companyId, tokenUser);
                if (ObjectUtils.isEmpty(empInfoDO)) {
                    continue;
                }
                EmpSocRelatedDO empSocRelatedDO = empSocRelatedService.selectByEmpId(empInfoDO.getId(), tokenUser.getSiteId());
                if (ObjectUtils.isEmpty(empSocRelatedDO.getSocIncreaseDate())) {
                    empSocRelatedDO.setSocIncreaseDate(DateUtils.getDateByDateStr(syncSocWebSiteDTO.getStartDate()));
                    empSocRelatedDO.setSocState(NORMAL_SOC.getValue());
                    empSocRelatedService.updateByIdSelective(empSocRelatedDO, tokenUser.getSiteId(), tokenUser.getUserId());
                }
                // 再根据缴费类型分组
                Map<String, List<SyncSocUniversalDTO>> payDetailGroupPayPostType =
                        payDetailOneEmp.stream().collect(Collectors.groupingBy(SyncSocUniversalDTO::getPayCostType));
                for (String payPostType : payDetailGroupPayPostType.keySet()) {
                    List<SyncSocUniversalDTO> payDetailPayPostType = payDetailGroupPayPostType.get(payPostType);
                    if (NORMAL_PAY_COST.getDesc().equals(payPostType)) {
                        EmpSocInfoDO empSocInfoDO =
                                empSocInfoService.selectEmpSocInfoByEmpIdAndMonthIdNormal(monthId, empInfoDO.getId(), companyId, tokenUser);
                        empSocInfoDO = checkSocEmpSocInfoExist(empSocInfoDO, monthId, yearAndMonth[0],
                                NORMAL_PAY_COST.getValue(), yearAndMonth[1], companyId, empInfoDO, tokenUser);
                        List<EmpSocItemDO> empSocItemList = new ArrayList<>();
                        for (SyncSocUniversalDTO payDetailDTO : payDetailPayPostType) {
                            empSocItemService.syncFillEmpSocInfoItem(payDetailDTO.getItemName(),
                                    empSocInfoDO.getId(), payDetailDTO.getCardinalityDefault(), payDetailDTO.getAmountCompany(),
                                    payDetailDTO.getAmountPersonal(), null, null, empSocItemList,
                                    cardinalityDefaultGroupType, 1, tokenUser);

                            resultList.add(payDetailDTO);
                        }
                        empSocItemDAO.insertListAndSetId(empSocItemList);
                        calculationAmount(Collections.singletonList(empSocInfoDO), tokenUser);
                    } else if (FILL_DIFFERENCE.getDesc().equals(payPostType)) {
                        socDifOrCol(payDetailPayPostType, monthId, empInfoDO, companyId, cardinalityDefaultGroupType,
                                resultList, FILL_DIFFERENCE.getValue(), tokenUser);
                    } else if (FILL_COLLECT.getDesc().equals(payPostType)) {
                        socDifOrCol(payDetailPayPostType, monthId, empInfoDO, companyId, cardinalityDefaultGroupType,
                                resultList, FILL_COLLECT.getValue(), tokenUser);
                    }
                }
            }
        }
        return resultList;
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public List<SyncSocUniversalDTO> batchSyncMeInfo(SyncSocWebSiteDTO syncSocWebSiteDTO, TokenUser tokenUser) {
        List<SyncSocUniversalDTO> resultList = new ArrayList<>();
        String companyId = syncSocWebSiteDTO.getCompanyId();
        // 拿过来前端传过来的数据
        List<QdMedicalInsuranceDTO> medicalInsuranceList =
                JSONObject.parseArray(syncSocWebSiteDTO.getMeInfo(), QdMedicalInsuranceDTO.class);
        if (CollectionUtils.isEmpty(medicalInsuranceList)) {
            return new ArrayList<>();
        }
        List<SyncSocUniversalDTO> syncSocUniversalList =
                BeanCopyUtil.beanListCopy(medicalInsuranceList, SyncSocUniversalDTO.class);
        parseSyncSocUniversalDTOList(syncSocUniversalList);
        // 按照缴费所属年月分组
        Map<String, List<SyncSocUniversalDTO>> qdMedicalInsuranceGroupDate = syncSocUniversalList.stream()
                .collect(Collectors.groupingBy(SyncSocUniversalDTO::getPaymentBelongsDate));
        for (String dateStr : qdMedicalInsuranceGroupDate.keySet()) {
            String[] yearAndMonth = DateUtils.getYearAndMonthByDateString(dateStr);
            String monthId;
            monthId = empSocMonthService.selectMonthIdByYearAndMonth(companyId, yearAndMonth[0],
                    yearAndMonth[1], tokenUser.getSiteId());
            if (StringUtils.isEmpty(monthId)) {
                monthId = empSocMonthService
                        .saveByYearAndMonth(companyId, yearAndMonth[0], yearAndMonth[1], tokenUser)
                        .getId();
            }
            List<SyncSocUniversalDTO> qdMedicalInsuranceList = qdMedicalInsuranceGroupDate.get(dateStr);
            // 在根据缴费所属年月的基础上按照员工姓名分组
            Map<String, List<SyncSocUniversalDTO>> qdWebSitePayDetailGroupName =
                    qdMedicalInsuranceList.stream().collect(Collectors.groupingBy(SyncSocUniversalDTO::getEmpName));
            for (String empNameKey : qdWebSitePayDetailGroupName.keySet()) {
                List<SyncSocUniversalDTO> qdMedicalInsuranceOneEmp = qdWebSitePayDetailGroupName.get(empNameKey);
                String empName = qdMedicalInsuranceOneEmp.get(0).getEmpName();
                String idCard = qdMedicalInsuranceOneEmp.get(0).getIdCard();
                // 查询花名册有无此人
                EmpInfoDO empInfoDO = empInfoService.selectEmpByNameAndIdCard(empName, idCard, companyId, tokenUser);
                if (ObjectUtils.isEmpty(empInfoDO)) {
                    continue;
                }
                EmpSocRelatedDO empSocRelatedDO = empSocRelatedService.selectByEmpId(empInfoDO.getId(), tokenUser.getSiteId());
                if (ObjectUtils.isEmpty(empSocRelatedDO.getMeIncreaseDate())) {
                    empSocRelatedDO.setMeIncreaseDate(DateUtils.getDateByDateStr(syncSocWebSiteDTO.getStartDate()));
                    empSocRelatedDO.setMeState(NORMAL_SOC.getValue());
                    empSocRelatedService.updateByIdSelective(empSocRelatedDO, tokenUser.getSiteId(), tokenUser.getUserId());
                }
                if (ObjectUtils.isEmpty(empInfoDO.getSocDate())) {
                    empInfoDO.setSocDate(DateUtils.getDateByDateStr(syncSocWebSiteDTO.getStartDate()));
                    empInfoDO.setEmpSocStatus(NORMAL_SOC.getValue());
                    empInfoService.updateByIdSelective(empInfoDO, tokenUser.getSiteId(), tokenUser.getUserId());
                }
                Map<String, List<SyncSocUniversalDTO>> qdWebSitePayDetailGroupPayPostType =
                        qdMedicalInsuranceOneEmp.stream().collect(Collectors.groupingBy(SyncSocUniversalDTO::getPayCostType));
                for (String payCostType : qdWebSitePayDetailGroupPayPostType.keySet()) {
                    List<SyncSocUniversalDTO> qdMedicalInsurances = qdWebSitePayDetailGroupPayPostType.get(payCostType);
                    if (NORMAL_PAY_COST.getDesc().equals(payCostType)) {
                        EmpSocInfoDO empSocInfoDO =
                                empSocInfoService.selectEmpSocInfoByEmpIdAndMonthIdNormal(monthId, empInfoDO.getId(), companyId, tokenUser);
                        empSocInfoDO = checkMeEmpSocInfoExist(empSocInfoDO, monthId, yearAndMonth[0],
                                NORMAL_PAY_COST.getValue(), yearAndMonth[1], companyId, empInfoDO, tokenUser);
                        List<EmpSocItemDO> empSocItemList = new ArrayList<>();
                        for (SyncSocUniversalDTO qdMedicalInsuranceDTO : qdMedicalInsurances) {
                            empSocItemService.syncFillEmpSocInfoItem(qdMedicalInsuranceDTO.getItemName(),
                                    empSocInfoDO.getId(), qdMedicalInsuranceDTO.getCardinalityDefault(), qdMedicalInsuranceDTO.getAmountCompany(),
                                    qdMedicalInsuranceDTO.getAmountPersonal(), null, null, empSocItemList,
                                    null, 3, tokenUser);
                            resultList.add(qdMedicalInsuranceDTO);
                        }
                        empSocItemDAO.insertListAndSetId(empSocItemList);
                        calculationAmount(Collections.singletonList(empSocInfoDO), tokenUser);
                    } else if (FILL_DIFFERENCE.getDesc().equals(payCostType)) {
                        meDifOrCol(qdMedicalInsurances, monthId, empInfoDO, companyId, resultList,
                                FILL_DIFFERENCE.getValue(), tokenUser);
                    } else if (FILL_COLLECT.getDesc().equals(payCostType)) {
                        meDifOrCol(qdMedicalInsurances, monthId, empInfoDO, companyId, resultList,
                                FILL_COLLECT.getValue(), tokenUser);
                    }
                }
            }
        }
        return resultList;
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public List<SyncSocUniversalDTO> batchSyncPfInfo(SyncSocWebSiteDTO syncSocWebSiteDTO, TokenUser tokenUser) {
        List<SyncSocUniversalDTO> resultList = new ArrayList<>();
        long currentTimeMillis = System.currentTimeMillis();
        SocAccountDTO socAccountDTO = cache.get(CacheKeyKit.getPfAccount(tokenUser.getUserId(), syncSocWebSiteDTO.getAreaId()));
        if (ObjectUtils.isEmpty(socAccountDTO)) {
            throw new ParamException("请重新登录公积金账号/或刷新公积金账号页面");
        }
        // 得先调一次获取total,根据total拿到页数
        String payDetailInfoPfBody = QdSocWebSite.getPayDetailInfoPf(socAccountDTO.getCookie(), 0, Long.toString(currentTimeMillis));
        JSONObject payDetailInfoPfJsonObject = JSON.parseObject(payDetailInfoPfBody);
        if (ObjectUtils.isEmpty(payDetailInfoPfJsonObject)) {
            return new ArrayList<>();
        }
        Integer total = payDetailInfoPfJsonObject.getJSONObject("APP_HEAD").getInteger("TOT_NUM");
        int maxPage = (total + 30 - 1) / 30;
        // 拿到第0页的数据
        String recMsg = payDetailInfoPfJsonObject.getJSONObject("BODY").getString("RecMsg");
        List<QdWebSitePayPfDetailDTO> zeroPageDateList = JSONObject.parseArray(recMsg, QdWebSitePayPfDetailDTO.class);
        List<QdWebSitePayPfDetailDTO> totalQdWebSitePayDetailDTO = new ArrayList<>(zeroPageDateList);
        //循环剩下的几页数据
        for (int i = 1; i < maxPage; i++) {
            String payDetailInfo = QdSocWebSite.getPayDetailInfoPf(socAccountDTO.getCookie(), i, Long.toString(currentTimeMillis));
            String data = JSON.parseObject(payDetailInfo).getJSONObject("BODY").getString("RecMsg");
            List<QdWebSitePayPfDetailDTO> qdWebSitePayDetailList = JSONObject.parseArray(data, QdWebSitePayPfDetailDTO.class);
            totalQdWebSitePayDetailDTO.addAll(qdWebSitePayDetailList);
        }
        List<SyncSocUniversalDTO> syncSocUniversalList =
                BeanCopyUtil.beanListCopy(totalQdWebSitePayDetailDTO, SyncSocUniversalDTO.class);
        parseSyncSocUniversalDTOList(syncSocUniversalList);
        List<String> monthIdList = empSocMonthService.selectCurrentDateAfterMonthId(syncSocWebSiteDTO.getStartDate(),
                syncSocWebSiteDTO.getEndDate(), syncSocWebSiteDTO.getCompanyId(), tokenUser.getSiteId());
        if (CollectionUtils.isEmpty(monthIdList)) {
            return new ArrayList<>();
        }
        for (String monthId : monthIdList) {
            EmpSocMonthDO empSocMonthDO = empSocMonthService.selectDOById(monthId, tokenUser.getSiteId());
            for (SyncSocUniversalDTO payPfDetailDTO : syncSocUniversalList) {
                payPfDetailDTO.setPaymentBelongsDate(empSocMonthDO.getYear() + empSocMonthDO.getMonth());
                String empName = payPfDetailDTO.getEmpName();
                String idCard = payPfDetailDTO.getIdCard();
                // 查询花名册有无此人
                EmpInfoDO empInfoDO = empInfoService.selectEmpByNameAndIdCard(empName, idCard, syncSocWebSiteDTO.getCompanyId(), tokenUser);
                if (ObjectUtils.isEmpty(empInfoDO)) {
                    continue;
                }
                EmpSocRelatedDO empSocRelatedDO = empSocRelatedService.selectByEmpId(empInfoDO.getId(), tokenUser.getSiteId());
                if (ObjectUtils.isEmpty(empSocRelatedDO.getPfIncreaseDate())) {
                    empSocRelatedDO.setPfIncreaseDate(DateUtils.getDateByDateStr(syncSocWebSiteDTO.getStartDate()));
                    empSocRelatedDO.setPfState(NORMAL_SOC.getValue());
                    empSocRelatedService.updateByIdSelective(empSocRelatedDO, tokenUser.getSiteId(), tokenUser.getUserId());
                }
                if (ObjectUtils.isEmpty(empInfoDO.getSocDate())) {
                    empInfoDO.setSocDate(DateUtils.getDateByDateStr(syncSocWebSiteDTO.getStartDate()));
                    empInfoDO.setEmpSocStatus(NORMAL_SOC.getValue());
                    empInfoService.updateByIdSelective(empInfoDO, tokenUser.getSiteId(), tokenUser.getUserId());
                }
                String empSocInfoId;
                EmpSocInfoDO empSocInfoDO =
                        empSocInfoService.selectEmpSocInfoByEmpIdAndMonthIdNormal(monthId, empInfoDO.getId(), syncSocWebSiteDTO.getCompanyId(), tokenUser);
                if (!ObjectUtils.isEmpty(empSocInfoDO)) {
                    empSocInfoId = empSocInfoDO.getId();
                    List<EmpSocItemDO> empSocItemDelete = empSocItemService.selectByEmpSocId(empSocInfoId, tokenUser.getSiteId());
                    empSocItemDelete.parallelStream().forEach(empSocItemDO -> {
                        if ("公积金".equals(empSocItemDO.getItemName())) {
                            empSocItemDAO.delete(empSocItemDO);
                        }
                    });
                } else {
                    empSocInfoDO = new EmpSocInfoDO();
                    empSocInfoService.syncFillEmpSocInfo(empSocInfoDO, monthId, empSocMonthDO.getYear(), empSocMonthDO.getMonth(),
                            syncSocWebSiteDTO.getCompanyId(), empInfoDO.getId(), NORMAL_PAY_COST.getDesc());
                    EmpSocInfoDO result = empSocInfoService.save(empSocInfoDO, tokenUser.getSiteId(), tokenUser.getUserId());
                    empSocInfoId = result.getId();
                }
                // 个人社保金额,公司社保金额
                empSocItemService.syncFillEmpSocInfoItem("公积金", empSocInfoId,
                        payPfDetailDTO.getCardinalityDefault(), payPfDetailDTO.getAmountCompany(),
                        payPfDetailDTO.getAmountPersonal(), payPfDetailDTO.getProportionCompany(),
                        payPfDetailDTO.getProportionPersonal(), null,
                        null, 2, tokenUser);
                empSocInfoDO.setPersonalPfAmount(new BigDecimal(payPfDetailDTO.getAmountPersonal()));
                empSocInfoDO.setCompanyPfAmount(new BigDecimal(payPfDetailDTO.getAmountCompany()));
                if (ObjectUtils.isEmpty(empSocInfoDO.getCompanySocAmount())) {
                    empSocInfoDO.setCompanyPfAmount(new BigDecimal("0"));
                }
                if (ObjectUtils.isEmpty(empSocInfoDO.getPersonalSocAmount())) {
                    empSocInfoDO.setPersonalPfAmount(new BigDecimal("0"));
                }
                empSocInfoService.updateByIdSelective(empSocInfoDO, tokenUser.getSiteId(), tokenUser.getUserId());
                resultList.add(payPfDetailDTO);
            }
        }
        return resultList;
    }

    @Override
    public Map<String, List<SyncSocUniversalDTO>> checkInfo(SocCheckCustomQuery socCheckCustomQuery, TokenUser tokenUser) {
        String checkDateStr = socCheckCustomQuery.getYear() + socCheckCustomQuery.getMonth();
        Map<String, List<SyncSocUniversalDTO>> result = new HashMap<>(8);
        if (socCheckCustomQuery.getSocIsTrue()) {
            SocAccountDTO socAccountDTO =
                    cache.get(CacheKeyKit.getSocAccount(tokenUser.getUserId(), socCheckCustomQuery.getAreaId()));
            if (ObjectUtils.isEmpty(socAccountDTO)) {
                throw new HrException("社保网站未登录或已过期,请重新登录或刷新社保网站");
            }
            // 得先调一次获取total,根据total拿到页数
            String payDetailInfoBody = QdSocWebSite.getPayDetailInfo(checkDateStr, checkDateStr,
                    socAccountDTO.getCookie(), 0);
            JSONObject responseDate = JSON.parseObject(payDetailInfoBody);
            if (!ObjectUtils.isEmpty(responseDate)) {
                Integer total = responseDate.getInteger("total");
                int maxPage = (total + 100 - 1) / 100;
                // 拿到第0页的数据
                String zeroPageDate = JSON.parseObject(payDetailInfoBody).getString("data");
                List<QdWebSitePayDetailDTO> zeroPageDateList = JSONObject.parseArray(zeroPageDate, QdWebSitePayDetailDTO.class);
                if (!CollectionUtils.isEmpty(zeroPageDateList)) {
                    List<QdWebSitePayDetailDTO> totalQdWebSitePayDetailDTO = new ArrayList<>(zeroPageDateList);
                    //循环剩下的几页数据
                    for (int i = 1; i < maxPage; i++) {
                        String payDetailInfo = QdSocWebSite.getPayDetailInfo(checkDateStr, checkDateStr,
                                socAccountDTO.getCookie(), i);
                        String data = JSON.parseObject(payDetailInfo).getString("data");
                        List<QdWebSitePayDetailDTO> qdWebSitePayDetailList = JSONObject.parseArray(data, QdWebSitePayDetailDTO.class);
                        totalQdWebSitePayDetailDTO.addAll(qdWebSitePayDetailList);
                    }
                    // 对象 copy 为通用对象
                    List<SyncSocUniversalDTO> syncSocUniversalList =
                            BeanCopyUtil.beanListCopy(totalQdWebSitePayDetailDTO, SyncSocUniversalDTO.class);
                    parseSyncSocUniversalDTOList(syncSocUniversalList);
                    for (SyncSocUniversalDTO syncSocUniversalDTO : syncSocUniversalList) {
                        syncSocUniversalDTO.setItemType(1);
                    }
                    result.put(SOC, syncSocUniversalList);
                }
            }
        }
        if (socCheckCustomQuery.getMeIsTrue()) {
            List<QdMedicalInsuranceDTO> medicalInsuranceList =
                    JSONObject.parseArray(socCheckCustomQuery.getMeInfo(), QdMedicalInsuranceDTO.class);
            if (!CollectionUtils.isEmpty(medicalInsuranceList)) {
                List<SyncSocUniversalDTO> syncSocUniversalList =
                        BeanCopyUtil.beanListCopy(medicalInsuranceList, SyncSocUniversalDTO.class);
                parseSyncSocUniversalDTOList(syncSocUniversalList);
                for (SyncSocUniversalDTO syncSocUniversalDTO : syncSocUniversalList) {
                    syncSocUniversalDTO.setItemType(1);
                }
                result.put(ME, syncSocUniversalList);
            }
        }
        if (socCheckCustomQuery.getPfIsTrue()) {
            SocAccountDTO socAccountDTO = cache.get(CacheKeyKit.getPfAccount(tokenUser.getUserId(), socCheckCustomQuery.getAreaId()));
            if (ObjectUtils.isEmpty(socAccountDTO)) {
                throw new HrException("公积金网站未登录或已过期,请重新登录或刷新公积金网站");
            }
            long currentTimeMillis = System.currentTimeMillis();
            // 得先调一次获取total,根据total拿到页数
            String payDetailInfoPfBody = QdSocWebSite.getPayDetailInfoPf(socAccountDTO.getCookie(), 0,
                    Long.toString(currentTimeMillis));
            JSONObject payDetailInfoPfJsonObject = JSON.parseObject(payDetailInfoPfBody);
            if (!ObjectUtils.isEmpty(payDetailInfoPfJsonObject)) {
                Integer total = payDetailInfoPfJsonObject.getJSONObject("APP_HEAD").getInteger("TOT_NUM");
                int maxPage = (total + 30 - 1) / 30;
                // 拿到第0页的数据
                String recMsg = payDetailInfoPfJsonObject.getJSONObject("BODY").getString("RecMsg");
                List<QdWebSitePayPfDetailDTO> zeroPageDateList = JSONObject.parseArray(recMsg, QdWebSitePayPfDetailDTO.class);
                List<QdWebSitePayPfDetailDTO> totalQdWebSitePayDetailDTO = new ArrayList<>(zeroPageDateList);
                //循环剩下的几页数据
                for (int i = 1; i < maxPage; i++) {
                    String payDetailInfo = QdSocWebSite.getPayDetailInfoPf(socAccountDTO.getCookie(), i,
                            Long.toString(currentTimeMillis));
                    String data = JSON.parseObject(payDetailInfo).getJSONObject("BODY").getString("RecMsg");
                    List<QdWebSitePayPfDetailDTO> qdWebSitePayDetailList = JSONObject.parseArray(data, QdWebSitePayPfDetailDTO.class);
                    totalQdWebSitePayDetailDTO.addAll(qdWebSitePayDetailList);
                }
                List<SyncSocUniversalDTO> syncSocUniversalList =
                        BeanCopyUtil.beanListCopy(totalQdWebSitePayDetailDTO, SyncSocUniversalDTO.class);
                parseSyncSocUniversalDTOList(syncSocUniversalList);
                for (SyncSocUniversalDTO syncSocUniversalDTO : syncSocUniversalList) {
                    syncSocUniversalDTO.setItemType(2);
                }
                result.put(PF, syncSocUniversalList);
            }
        }
        return result;
    }

    private void parseSyncSocUniversalDTOList(List<SyncSocUniversalDTO> syncSocUniversalDTOList) {
        for (SyncSocUniversalDTO syncSocUniversalDTO : syncSocUniversalDTOList) {
            if ("基本医疗".equals(syncSocUniversalDTO.getItemName())) {
                syncSocUniversalDTO.setItemName("医疗保险");
            } else if (StringUtils.isEmpty(syncSocUniversalDTO.getItemName())) {
                syncSocUniversalDTO.setItemName("公积金");
            } else if ("生育保险".equals(syncSocUniversalDTO.getItemName())) {
                syncSocUniversalDTO.setItemName("生育保险");
            } else {
                syncSocUniversalDTO.setItemName(QdWebSiteSocTypeIndex.find(syncSocUniversalDTO.getItemName()).getDesc());
            }
            if ("正常应缴".equals(syncSocUniversalDTO.getPayCostType())) {
                syncSocUniversalDTO.setPayCostType(NORMAL_PAY_COST.getDesc());
            } else if ("社平调整补差".equals(syncSocUniversalDTO.getPayCostType())) {
                syncSocUniversalDTO.setPayCostType(FILL_DIFFERENCE.getDesc());
            } else if ("全额补收".equals(syncSocUniversalDTO.getPayCostType()) ||
                    "征缴规则变更补收".equals(syncSocUniversalDTO.getPayCostType())) {
                syncSocUniversalDTO.setPayCostType(FILL_COLLECT.getDesc());
            } else if (StringUtils.isEmpty(syncSocUniversalDTO.getPayCostType())) {
                syncSocUniversalDTO.setPayCostType(NORMAL_PAY_COST.getDesc());
            } else if ("A182".equals(syncSocUniversalDTO.getPayCostType())) {
                syncSocUniversalDTO.setPayCostType(FILL_DIFFERENCE.getDesc());
            } else {
                syncSocUniversalDTO.setPayCostType(QdWebSiteDeclReason.find(syncSocUniversalDTO.getPayCostType()).getDesc());
            }
            if(!"0".equals(syncSocUniversalDTO.getAmountPersonal())){
                syncSocUniversalDTO.setAmountPersonal(syncSocUniversalDTO.getAmountPersonal().replaceAll("(0)+$", ""));
            }
            if(!"0".equals(syncSocUniversalDTO.getAmountCompany())){
                syncSocUniversalDTO.setAmountCompany(syncSocUniversalDTO.getAmountCompany().replaceAll("(0)+$", ""));
            }
        }
    }


    /**
     * 社保网站,调整计划,补收逻辑
     */
    private void socDifOrCol(List<SyncSocUniversalDTO> payDetailPayPostType, String monthId, EmpInfoDO empInfoDO, String companyId,
                             Map<String, QingDaoCardinalityDefaultDTO> cardinalityDefaultGroupType,
                             List<SyncSocUniversalDTO> resultList, Integer payCostType, TokenUser tokenUser) {
        List<EmpSocInfoDO> update = new ArrayList<>();
        List<String> check = new ArrayList<>();
        List<EmpSocItemDO> empSocItemList = new ArrayList<>();
        for (SyncSocUniversalDTO payDetailDTO : payDetailPayPostType) {
            String paymentDate = payDetailDTO.getPaymentBelongsDate();
            String year = paymentDate.substring(0, 4);
            String month = paymentDate.substring(4);
            EmpSocInfoDO empSocInfoDO = empSocInfoService.selectEmpSocInfoByEmpIdAndMonthIdDifCol(monthId, empInfoDO.getId(),
                    companyId, year, month, payCostType, tokenUser);
            empSocInfoDO = checkSocEmpSocInfoExist(empSocInfoDO, monthId, year, payCostType,
                    month, companyId, empInfoDO, tokenUser);
            if (FILL_COLLECT.getValue().equals(payCostType)) {
                empSocInfoDO.setSupplementType("1");
            }
            // 个人社保金额,公司社保金额
            empSocItemService.syncFillEmpSocInfoItem(payDetailDTO.getItemName(),
                    empSocInfoDO.getId(), payDetailDTO.getCardinalityDefault(), payDetailDTO.getAmountCompany(),
                    payDetailDTO.getAmountPersonal(), null, null, empSocItemList,
                    cardinalityDefaultGroupType, 1, tokenUser);
            if (!check.contains(empSocInfoDO.getId())) {
                update.add(empSocInfoDO);
                check.add(empSocInfoDO.getId());
            }
            resultList.add(payDetailDTO);
        }
        empSocItemDAO.insertListAndSetId(empSocItemList);
        calculationAmount(update, tokenUser);
    }

    /**
     * 计算金额
     */
    private void calculationAmount(List<EmpSocInfoDO> updateList, TokenUser tokenUser) {
        for (EmpSocInfoDO empSocInfoDO : updateList) {
            BigDecimal personalPf = new BigDecimal("0");
            BigDecimal companySoc = new BigDecimal("0");
            BigDecimal companyPf = new BigDecimal("0");
            BigDecimal personalSoc = new BigDecimal("0");
            List<EmpSocItemDO> empSocItemList = empSocItemService.selectByEmpSocId(empSocInfoDO.getId(), tokenUser.getSiteId());
            for (EmpSocItemDO empSocItemDO : empSocItemList) {
                if (SOC_ITEM_TYPE.equals(empSocItemDO.getItemType()) ||
                        ME_ITEM_TYPE.equals(empSocItemDO.getItemType())) {
                    personalSoc = personalSoc.add(empSocItemDO.getAmountPersonal());
                    companySoc = companySoc.add(empSocItemDO.getAmountCompany());
                } else {
                    personalPf = personalPf.add(empSocItemDO.getAmountPersonal());
                    companyPf = companyPf.add(empSocItemDO.getAmountCompany());
                }
            }
            empSocInfoDO.setPersonalPfAmount(personalPf);
            empSocInfoDO.setPersonalSocAmount(personalSoc);
            empSocInfoDO.setCompanyPfAmount(companyPf);
            empSocInfoDO.setCompanySocAmount(companySoc);
            empSocInfoService.updateByIdSelective(empSocInfoDO);
        }
    }

    /**
     * 社保网站,检测empSocInFo是否存在
     */
    private EmpSocInfoDO checkSocEmpSocInfoExist(EmpSocInfoDO empSocInfoDO, String monthId, String year, Integer payCostType,
                                                 String month, String companyId, EmpInfoDO empInfoDO, TokenUser tokenUser) {
        if (!ObjectUtils.isEmpty(empSocInfoDO)) {
            List<EmpSocItemDO> empSocItemDelete = empSocItemService.selectByEmpSocIdAndItemType(empSocInfoDO.getId(),
                    SOC_ITEM_TYPE, tokenUser.getSiteId());
            if (!CollectionUtils.isEmpty(empSocItemDelete)) {
                empSocItemService.deleteByDoList(empSocItemDelete);
            }
        } else {
            empSocInfoDO = new EmpSocInfoDO();
            empSocInfoService.syncFillEmpSocInfo(empSocInfoDO, monthId, year, month,
                    companyId, empInfoDO.getId(), SocPayCostType.find(payCostType).getDesc());
            empSocInfoDO = empSocInfoService.save(empSocInfoDO, tokenUser.getSiteId(), tokenUser.getUserId());
        }
        return empSocInfoDO;
    }

    /**
     * 医保网站,调整计划,补收逻辑
     */
    private void meDifOrCol(List<SyncSocUniversalDTO> qdMedicalInsurances, String monthId, EmpInfoDO empInfoDO, String companyId,
                            List<SyncSocUniversalDTO> resultList, Integer payCostType, TokenUser tokenUser) {
        List<EmpSocInfoDO> update = new ArrayList<>();
        List<String> check = new ArrayList<>();
        for (SyncSocUniversalDTO qdMedicalInsurance : qdMedicalInsurances) {
            String paymentDate = qdMedicalInsurance.getPaymentDate();
            String year = paymentDate.substring(0, 4);
            String month = paymentDate.substring(4);
            EmpSocInfoDO empSocInfoDO =
                    empSocInfoService.selectEmpSocInfoByEmpIdAndMonthIdDifCol(monthId, empInfoDO.getId(),
                            companyId, year, month, payCostType, tokenUser);
            empSocInfoDO = checkMeEmpSocInfoExist(empSocInfoDO, monthId, year, payCostType,
                    month, companyId, empInfoDO, tokenUser);
            // 个人社保金额,公司社保金额
            empSocItemService.syncFillEmpSocInfoItem(qdMedicalInsurance.getItemName(),
                    empSocInfoDO.getId(), qdMedicalInsurance.getCardinalityDefault(), qdMedicalInsurance.getAmountCompany(),
                    qdMedicalInsurance.getAmountPersonal(), null, null, null,
                    null, 3, tokenUser);
            if (!check.contains(empSocInfoDO.getId())) {
                update.add(empSocInfoDO);
                check.add(empSocInfoDO.getId());
            }
            resultList.add(qdMedicalInsurance);
        }
        calculationAmount(update, tokenUser);
    }

    /**
     * 医保网站,检测empSocInFo是否存在
     */
    private EmpSocInfoDO checkMeEmpSocInfoExist(EmpSocInfoDO empSocInfoDO, String monthId, String year, Integer payCostType,
                                                String month, String companyId, EmpInfoDO empInfoDO, TokenUser tokenUser) {
        if (!ObjectUtils.isEmpty(empSocInfoDO)) {
            List<EmpSocItemDO> empSocItemDelete = empSocItemService.selectByEmpSocIdAndItemType(empSocInfoDO.getId(),
                    ME_ITEM_TYPE, tokenUser.getSiteId());
            if (!CollectionUtils.isEmpty(empSocItemDelete)) {
                empSocItemService.deleteByDoList(empSocItemDelete);
            }
        } else {
            empSocInfoDO = new EmpSocInfoDO();
            empSocInfoService.syncFillEmpSocInfo(empSocInfoDO, monthId, year, month,
                    companyId, empInfoDO.getId(), SocPayCostType.find(payCostType).getDesc());
            empSocInfoDO = empSocInfoService.save(empSocInfoDO, tokenUser.getSiteId(), tokenUser.getUserId());
        }
        return empSocInfoDO;
    }
}
